/// <reference path="../routing/HttpRequest.js" />
/// <reference path="../utilities/FXDom.js" />
/// <reference path="../utilities/ManualResetEvent.js" />
/// <reference path="../utilities/Markup.js" />
/// <reference path="../utilities/ModerationQueueStatus.js" />
/// <reference path="../utilities/Post.js" />
/// <reference path="../utilities/Xpcom.js" />
///--------------------------------------------------------------------
/// <file name="QuickEdit.js">
///   Allows posts to be edited inside of the post screen.
/// </file>
///--------------------------------------------------------------------

NAMFox.ns(function() { with (NAMFox) {

this.QuickEdit = function(_$, htmlDocument, threadData) {
    /// <summary>Initializes a new instance of the QuickEdit class.</summary>
    /// <param name="_$" type="FXDom">
    ///   The FXDom selector that allows this QuickEdit instance
    ///   to select DOM elements from the page itself.
    /// </param>
    /// <param name="htmlDocument" type="Document">
    ///   The HTML Document object for the current page.
    /// </param>
    /// <param name="threadData">
    ///   Contains various data about the thread as well
    ///   as features added on the thread itself, like Quick Edit.
    /// </param>
    
    this._$ = _$;
    this._htmlDocument = htmlDocument;
    this._threadData = threadData;
};

QuickEdit.errorExpr = /<table align=center width=450[\s\S]*?<\/table>/;

QuickEdit.prototype = {
    _beginProcess: function(postId) {
        /// <summary>
        ///   Indicates in the user interface that
        ///   the edit is being made.
        /// </summary>
        
        this._$("#namfox-quick-edit-action-container-" + postId + " input").attr("disabled", true);
        this._$("#namfox-quick-edit-loading-image-" + postId).css("display", "inline");
        this._$("#namfox-quick-edit-response-message-" + postId).html("");
        this._$("#namfox-quick-edit-status-" + postId).attr("className", "");
    },
    
    _changePostToTextArea: function(event, post) {
        /// <summary>
        ///   Handles the request to quick edit a particular post.
        /// </summary>
        /// <param name="post" type="Post">The Post object to edit.</param>
       
        // Don't invoke quick edit when a video is double clicked.
        if ($FX.nodeName(event.target, "embed")) {
            return;
        }

        var postContentCell = $FX(post.contentRow).find("td");
        if (event.target && $FX.nodeName(event.target, "a") && event.target.textContent === "quick edit" ||
            !postContentCell.find("embed").length && !postContentCell.find("iframe[src*=youtube]").length) {
            this._changePostToTextAreaCore(post);
        }
        else {
            switch ($.getConfig().quickEdit.disableDoubleClickForPostsWithMedia) {
                case -1:
                    var that = this;
                    this._sandbox.callback = function(invokeQuickEdit) {
                        if (that._$("#namfox-do-not-ask-again").attr("checked")) {
                            $.getConfig().quickEdit.disableDoubleClickForPostsWithMedia = invokeQuickEdit ? 0 : 1;
                        }

                        if (invokeQuickEdit) {
                            that._changePostToTextAreaCore.call(that, post);
                        }
                    };

                    // Warning: A dangerous or banned global object was accessed by some JavaScript code.
                    // Warning: Accessed object: evalInSandbox
                    // Here we only execute code and do not rely on return values inside our chrome-privileged script.
                    Components.utils.evalInSandbox(
                        'jQuery("#namfox-quick-edit-with-video").dialog("open");',
                        this._sandbox);
                    break;
                case 0:
                    this._changePostToTextAreaCore(post);
                    break;
            }
        }
    },
    
     _changePostToTextAreaCore: function(post) {
        var postContentCell = $FX(post.contentRow).find("td");
        if (!post.isInQuickEditMode) {
            post.isInQuickEditMode = true;
            
            var postId = post.getMessageId();
            post.oldHtml = postContentCell.html();
            
            // We're appending this fake text area to the end of the page in
            // order to determine the appropriate height for the new text area
            // in the quick edit window. By adding enough to text we can read
            // the text area's scrollHeight property and use that later on.
            
            // 76% =
            //   80% (the width of the table cell) *
            //   95% (the width of the text area within that table cell).
            $FX(this._htmlDocument.body).append(
                '<textarea id="namfox-quick-edit-textarea-' + postId + '" style="width: 76%; visibility: hidden;"></textarea>'
            );

            var that = this;
            function markupReceived(markup) {
                var textArea = that._$("#namfox-quick-edit-textarea-" + postId);
                var scrollHeight = textArea.val(markup).attr("scrollHeight");
                textArea.remove();
            
                var imageColor = post.getBackgroundColor().substr(1);
                var author = post.getAuthor();
                var hasSignature = post.isSignatureDisplayed();
                var isAuthorUser = author === $.getCurrentUser().userName;
            
                var allowedToMakeEdit = isAuthorUser || that._threadData.isUserModerator();
            
                var html = "";
                html += '<div id="namfox-quick-edit-container-' + postId + '">';
                html += '  <div class="namfox-quick-edit-response-message" id="namfox-quick-edit-response-message-' + postId +'"></div>';
                html += '  <div>';
                html += '    <div id="namfox-quick-edit-post-message-container-' + postId + '"></div>';
                html += '    <div>';
                html += '      <input class="namfox-quick-edit-subject" id="namfox-quick-edit-subject-' + postId + '"></input>';
                html += '      <textarea class="namfox-quick-edit-textarea" id="namfox-quick-edit-textarea-' + postId + '" style="height: ' + (scrollHeight + 50) + 'px;"></textarea>';
                html += '    </div>';
                html += '    <div id="namfox-quick-edit-markup-bar-' + postId + '"></div>';
                html += '  </div>';
            
                if (allowedToMakeEdit) {
                    html += '<div class="namfox-quick-edit-options-container">';
                    html += '  <div>';
                    html += '    <input id="namfox-quick-edit-signature-' + postId + '" type="checkbox"' + (hasSignature ? 'checked="checked"' : '') + '></input>';
                    html += '    <label for="namfox-quick-edit-signature-' + postId + '">Append signature to this post [ members only ]</label>';
                    html += '  </div>';
                    html += '</div>';
                    html += '<div class="namfox-quick-edit-submission">';
                    html += '  <img id="namfox-quick-edit-loading-image-' + postId + '" src="chrome://namfox/skin/posting/loading-' + imageColor + '.gif" style="display: none;" />';
                    html += '  <span id="namfox-quick-edit-status-' + postId + '"></span>';
                    html += '</div>';
                }
            
                html += '  <div class="namfox-quick-edit-action-container" id="namfox-quick-edit-action-container-' + postId + '">';
                html += '    <div class="namfox-quick-edit-core-button-row">';
            
                if (allowedToMakeEdit) {
                    html += '  <input id="namfox-quick-edit-submit-' + postId + '" type="button" value="Quick Edit" />';
                    html += '  <input id="namfox-quick-edit-quick-preview-' + postId + '" type="button" value="Preview" />';
                    html += '  <input id="namfox-quick-edit-full-preview-' + postId + '" type="button" value="Go to Full Edit" />';
                }
            
                html += '    </div>';
                html += '  <div class="namfox-quick-edit-peripheral-button-row">';
                html += '    <input id="namfox-quick-edit-cancel-' + postId + '" type="button" value="Cancel" />';
                html += '  </div>';
                html += '  </div>';
                html += '</div>';

                // Used to make sure users have a similar experience with the '@' notification that they do on native Neoseeker text areas.
                html += '<script>refresh_friendsArray($("#namfox-quick-edit-textarea-' + postId + '"));</script>';
            
                postContentCell.html(html);

                // Used to make sure users have a similar experience with the '@' notification that they do on native Neoseeker text areas.
                Sandbox.evalOnPage(
                    that._htmlDocument,
                    'refresh_friendsArray(jQuery("#namfox-quick-edit-textarea-' + postId + '"))',
                    {
                        jQuery: "$",
                        refresh_friendsArray: "refresh_friendsArray"
                    });
            
                textArea = that._$("#namfox-quick-edit-textarea-" + postId);
                that._htmlDocument.__namfox__.autoComplete.attachSingle(textArea);
                that._htmlDocument.__namfox__.textAreaController.attachSingle(textArea);
            
                if (allowedToMakeEdit) {
                     that._$("#namfox-quick-edit-markup-bar-" + postId).append(
                        Markup.create(
                            textArea,
                            MarkupLocation.QuickEdit,
                            Markup.bold,
                            Markup.italics,
                            Markup.underline,
                            Markup.quote,
                            Markup.linkName,
                            Markup.customMessages
                        )
                    );
                }

                that._$("#namfox-quick-edit-subject-" + postId).val(post.getSubject());
                textArea.val(markup);
            
                if (allowedToMakeEdit) {
                    that._$("#namfox-quick-edit-submit-" + postId).click(
                        $.createCallback(that._onQuickEditClicked, that, post)
                    );
                    that._$("#namfox-quick-edit-quick-preview-" + postId).click(
                        $.createCallback(that._onPreviewClicked, that, post)
                    );
                    that._$("#namfox-quick-edit-full-preview-" + postId).click(
                        $.createCallback(that._onFullEditRequested, that, post)
                    );
                }
            
                that._$("#namfox-quick-edit-cancel-" + postId).click(
                    $.createCallback(that._onCancelClicked, that, post)
                );
            }

            post.getMarkup(markupReceived);
        }
    },
    
    _endProcess: function(postId) {
        /// <summary>
        ///   Indicates in the user interface that the edit has completed.
        /// </summary>
        /// <param name="postId" type="String">
        ///   The ID of the Post for which the UI should be reset.
        /// </param>
        
        this._$("#namfox-quick-edit-action-container-" + postId + " input").attr("disabled", false);
        this._$("#namfox-quick-edit-loading-image-" + postId).css("display", "none");
        this._reportStatus(postId, "");
    },
    
    _executeEdit: function(post) {
        /// <summary>Carries out the edit logic for a particular post.</summary>
        /// <param name="post" type="Post">
        ///   The Post object on which to execute the edit.
        /// </param>
    
        var postId = post.getMessageId();
        var body = this._getBody(postId);
        
        var postData = {
            subject: $.urlEncode(this._getSubject(postId)),
            body: $.urlEncode(body),
            submit: true,
            "do": "submit",
            "function": "edit_message",
            messageid: postId
        };
        
        if (this._$("#namfox-quick-edit-signature-" + postId).attr("checked")) {
            postData.usesig = "Y";
        }
        
        $.post(
            $.url.forum("/index.php"),
            postData,
            $.createCallback(this._onQuickEditSubmitted, this, post),
            $.createCallback(this._onError, this, post, "edit"),
            $.cacheHandling.bypassCache
        );
    },
    
    _getBody: function(postId) {
        /// <summary>Gets the new post body for a specific post.</summary>
        /// <param name="postId">
        ///   The ID of the Post for which to retrieve the new body.
        /// </param>
        /// <returns type="String" />
        
        return this._$("#namfox-quick-edit-textarea-" + postId).val();
    },
    
    _getSubject: function(postId) {
        /// <summary>Gets the new post subject for a specific post.</summary>
        /// <param name="postId">
        ///   The ID of the Post for which to retrieve the new subject.
        /// </param>
        /// <returns type="String" />
        
        return this._$("#namfox-quick-edit-subject-" + postId).val();
    },
    
    _onCancelClicked: function(event, post) {
        /// <summary>Called when the cancel button is clicked.</summary>
        /// <param name="post" type="Post">
        ///   The Post object for which to cancel the edit.
        /// </param>
        
        $FX(post.contentRow).find("td").html(post.oldHtml);
        post.isInQuickEditMode = false;
        delete post.oldHtml;
    },
    
    _onError: function(xhr, causedByTimeout, post, caller) {
        /// <summary>Called when an AJAX request fails.</summary>
        /// <param name="xhr" type="XMLHttpRequest">
        ///   The XMLHttpRequest that failed.
        /// </param>
        /// <param name="causedByTimeout" type="Boolean">
        ///   Specifies whether the error was caused by a time out.
        /// </param>
        /// <param name="post" type="Post">
        ///   The Post object for which this error occurred.
        /// </param>
        /// <param name="caller" type="String">
        ///   A short description of the caller.
        /// </param>
        
        var postId = post.getMessageId();
        this._$("#namfox-quick-edit-status-" + postId).attr("className", "namfox-error");
        this._endProcess(postId);
        
        if (caller === "edit" && xhr.readyState >= 2) {
            this._htmlDocument.location.href = this._htmlDocument.location.href;
            return;
        }
        
        if (causedByTimeout) {
            this._reportStatus(postId, "Submission timed out. Please try again.");
        }
        else {
            this._reportStatus(postId, "Request failed unexpectedly. Please try again.");
        }
        
        $.info("Quick Edit request failed during " + caller);
    },
    
    _onFullEditRequested: function(event, post) {
        /// <summary>Called when the full edit button is clicked.</summary>
        /// <param name="post" type="Post">
        ///   The post object for which this edit is requested.
        /// </param>
        
        var postId = post.getMessageId();
        var body = this._$("#namfox-quick-edit-textarea-" + postId).val();
        var subject = this._$("#namfox-quick-edit-subject-" + postId).val();
        
        var form = '';
        form += '<form';
        form += '  id="namfox-quick-edit-full-form-' + postId + '"';
        form += '  method="POST"';
        form += '  action="' + $.url.forum("/index.php") + '"';
        form += '  enctype="application/x-www-form-urlencoded"';
        form += '  style="display: none;">';
        form += '  <input type="hidden" name="subject" value="' + $.attrEncode(subject) + '" />';
        form += '  <input type="hidden" name="body" value="' + $.attrEncode(body) + '" />';
        form += '  <input type="hidden" name="messageid" value="' + postId + '" />';
        form += '  <input type="hidden" name="submit" value="true" />';
        form += '  <input type="hidden" name="do" value="preview" />';
        form += '  <input type="hidden" name="function" value="edit_message" />';
        
        if (this._$("#namfox-quick-edit-signature-" + postId).attr("checked")) {
            form += '<input type="hidden" name="usesig" value="Y" />';
        }
        
        form += '</form>';
        
        this._$("body").append(form);
        this._$("#namfox-quick-edit-full-form-" + postId).get(0).submit();
    },
    
    _onPreviewClicked: function(event, post) {
        /// <summary>Called when the preview button is clicked.</summary>
        /// <param name="post" type="Post">
        ///   The post object for which this preview is requested.
        /// </param>
        
        var postId = post.getMessageId();
        
        this._beginProcess(postId);
        this._reportStatus(postId, "Getting preview...");
        
        var postData = {
            subject: $.urlEncode(this._getSubject(postId)),
            body: $.urlEncode(this._getBody(postId)),
            submit: true,
            "do": "preview",
            "function": "edit_message",
            messageid: postId
        };
        
        if (this._$("#namfox-quick-edit-signature-" + postId).attr("checked")) {
            postData.usesig = "Y";
        }
        
        $.post(
            $.url.forum("/index.php"),
            postData,
            $.createCallback(this._onPreviewSubmitted, this, post),
            $.createCallback(this._onError, this, post, "preview")
        );
    },
    
    _onPreviewSubmitted: function(xhr, post) {
        /// <summary>
        ///   Called when the preview request yields a meaningful response.
        /// </summary>
        /// <param name="xhr" type="XMLHttpRequest">
        ///   The XMLHttpRequest for the preview request.
        /// </param>
        /// <param name="post" type="Post">
        ///   The post object for which this edit is requested.
        /// </param>
        
        var postId = post.getMessageId();
        var preview = xhr.responseText.match(QuickReply.previewResponseExpr);
        var error = xhr.responseText.match(QuickReply.previewErrorExpr);

        $.assert(preview, "Could not find a response that matched the preview regular expression");
        
        preview = (preview[1] || preview[0]).replace(QuickReply.spoilerExpr, "<div class=\"spoiler_header\" style=\"display: block;\">");

        if (error) {
            preview = error[0] + preview;
        }
        
        this._$("#namfox-quick-edit-response-message-" + postId).html(preview);
        this._endProcess(postId);
    },
    
    _onQuickEditClicked: function(event, post) {
        /// <summary>
        ///   Called when the "Quick Edit" aka submit button is clicked.
        /// </summary>
        /// <param name="post" type="Post">
        ///   The post object for which this edit is requested.
        /// </param>
        
        var postId = post.getMessageId();
        this._beginProcess(postId);
        this._reportStatus(postId, "Submitting edit...");
        
        this._executeEdit(post);
    },

    _reportStatus: function(postId, status) {
        /// <summary>Reports the current status of the quick edit.</summary>
        /// <param name="postId" type="Number">
        ///   The ID of the Post for which to change the status.
        /// </param>
        /// <param name="status" type="String">
        ///   The new status for the post.
        /// </param>
        
        this._$("#namfox-quick-edit-status-" + postId).html(status);
    },

    _onQuickEditSubmitted: function(xhr, post) {
        /// <summary>
        ///   Called when the quick edit was successfully submitted.
        /// </summary>
        /// <param name="xhr" type="XMLHttpRequest">
        ///   The XMLHttpRequest that submitted the edit.
        /// </param>
        /// <param name="post" type="Post">
        ///   The Post object for which this edit was submitted.
        /// </param>
        
        var error = xhr.responseText.match(QuickEdit.errorExpr);
        var postId = post.getMessageId();
        
        if (error) {
            this._$("#namfox-quick-edit-response-message-" + postId).html(error[0]);
        }
        else {
            var postHtml = xhr.responseText.match(post.getPostRegExp());
            
            if (postHtml) {
                postHtml = postHtml[0];
                
                $.verbose("QUICK EDIT | Found new post HTML after edit: " + postHtml);
                
                // For some reason on quick edit submit the spoilers do not execute their associated JavaScript
                // so they are not shown. However, this does not apply to preview, at which time the JavaScript
                // is executed so they ARE shown.
                postHtml = postHtml.replace(QuickReply.spoilerExpr, "<div class=\"spoiler_header\" style=\"display: block;\">");
                    
                post.setHtml(xhr.responseText);
                post.setSubject(this._getSubject(postId));

                // Since the regular expression match only finds the post content, and not
                // the content of the rest of the table cell, we need to find the old content
                // in our cached version of the table cell HTML, replace it with the new post
                // and then set the HTML for the whole table cell.
                var newHtml = post.oldHtml.replace(/<!-- msg[\s\S]*?<!-- endmsg.*? -->/, postHtml);
                $FX(post.contentRow).find("td").html(newHtml);
                post.isInQuickEditMode = false;
                this._htmlDocument.location.hash = "#" + post.getReplyNumber();
            }
        }
    },
    
    attach: function() {
        /// <summary>
        ///   Renders the quick edit UI on the view thread page.
        /// </summary>
        
        var posts = this._threadData.getPosts();
        var that = this;
        
        $FX.each(
            posts,
            function(i, post) {
                that.attachSingle.call(that, post);
            }
        );

        var dialog = '';
        dialog += '<div id="namfox-quick-edit-with-video">'
        dialog += '  <p><strong>Do you want to use quick edit, even though this post has videos in it?</strong></p>';
        dialog += '  <p><input type="checkbox" value="Y" id="namfox-do-not-ask-again"><label for="namfox-do-not-ask-again">Do not ask me again</label></p>';
        dialog += '</div>';
            
        this._$("body").append(dialog);
        this._sandbox = new Components.utils.Sandbox(this._htmlDocument.defaultView);
        this._sandbox.jQuery = this._htmlDocument.defaultView.wrappedJSObject.$;

        var dialogOptionsInit = '';
        dialogOptionsInit += 'var dialogOptions = {';
        dialogOptionsInit += '    height: 200,';
        dialogOptionsInit += '    width: 500,';
        dialogOptionsInit += '    autoOpen: false,';
        dialogOptionsInit += '    modal: true,';
        dialogOptionsInit += '    overlay: {';
        dialogOptionsInit += '        backgroundColor: "#E0E0E0",';
        dialogOptionsInit += '        opacity: 0.7';
        dialogOptionsInit += '    },';
        dialogOptionsInit += '    title: "Use Quick Edit?",';
        dialogOptionsInit += '    buttons: {';
        dialogOptionsInit += '        "Yes": function() {';
        dialogOptionsInit += '            jQuery("#namfox-quick-edit-with-video").dialog("close");';
        dialogOptionsInit += '            callback(true);';
        dialogOptionsInit += '        },';
        dialogOptionsInit += '        "No":  function() {';
        dialogOptionsInit += '            jQuery("#namfox-quick-edit-with-video").dialog("close");';
        dialogOptionsInit += '            callback(false);';
        dialogOptionsInit += '        }';
        dialogOptionsInit += '    }';
        dialogOptionsInit += '};';
        
        // Warning: A dangerous or banned global object was accessed by some JavaScript code.
        // Warning: Accessed object: evalInSandbox
        // Here we only execute code and do not rely on return values inside our chrome-privileged script.
        Components.utils.evalInSandbox(
            dialogOptionsInit + 'jQuery("#namfox-quick-edit-with-video").dialog(dialogOptions);',
            this._sandbox);
    },
    
    attachSingle: function(post) {
        /// <summary>
        ///   Renders the quick edit UI on the view thread page.
        /// </summary>
        /// <param name="post" type="Post">
        ///   The Post object on which to bestow quick edit functionality.
        /// </param>
        
        var moderationQueueStatus = post.getModerationQueueStatus();
                
        if (moderationQueueStatus.view === ViewStatus.InView ||
            moderationQueueStatus.moderator === ModeratorStatus.Moderator) { 
            var callback = $.createCallback(this._changePostToTextArea, this, post);
            if ($.getConfig().quickEdit.doubleClickEnabled) {
                $FX(post.contentRow).find("td").dblclick(callback);
            }
            
            var linkRow = $FX(post.linkRow);
            
            var quickEditImage = linkRow.find("img[src$=edit_message.gif]:even");
            
            if (quickEditImage.length === 0) {
                // A new Neoseeker version removes quick edit links if you're not a moderator
                // and you didn't author a post. We need to add them back.
                
                linkRow.find("a:contains(quick quote)").
                    after(' &nbsp; <img border="0" alt="" src="chrome://namfox/skin/posting/quickedit.gif" /> <a class="namfox-post-link" name="namfox-quick-edit-link">quick edit</a>');
            }
            else {
                quickEditImage.attr("src", "chrome://namfox/skin/posting/quickedit.gif");
                    
                linkRow.find("a:contains(quick edit)").
                    after('<a class="namfox-post-link" name="namfox-quick-edit-link">quick edit</a>').
                    remove();
            }
            
            linkRow.find("a[name=namfox-quick-edit-link]").click(callback);
        }
    }
};

}});